/**
 * Copyright 2007-2008. Chongqing First Information & Network Co., Ltd. All
 * rights reserved. <a>http://www.cqfirst.com.cn</a>
 */
package com.cqcis.uip.base.framework.utils;

import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;

import org.apache.mina.common.IoSession;

import com.cqcis.uip.base.framework.UIPServiceException;

/**
 * 封装 MINA 框架的ByteBuffer, 实现数据解包、封包
 * 
 * @author huangmy
 * @date   2007-12-20
 */
public class ByteBuffer {
	private org.apache.mina.common.ByteBuffer buffer;
	private IoSession ioSession; // session
	private boolean released; // 释放
	private boolean allocted; // 本身分配的
	
	@Override
	public String toString() {
		return buffer.toString();
	}
	
	/**
	 * 生成对应字节数组的ByteBuffer
	 * 
	 * @param byteArray
	 * @return
	 */
	public static ByteBuffer wrap(byte[] byteArray) {
		return new ByteBuffer(org.apache.mina.common.ByteBuffer.wrap(byteArray), false);
	}
	
	/**
	 * 封装nio缓冲
	 * 
	 * @param nioBuffer
	 * @return
	 */
	public static ByteBuffer wrap(java.nio.ByteBuffer nioBuffer) {
		return new ByteBuffer(org.apache.mina.common.ByteBuffer.wrap(nioBuffer), false);
	}
	
	/**
	 * 封装nio缓冲
	 * 
	 * @param nioBuffer
	 * @return
	 */
	public static ByteBuffer wrap(org.apache.mina.common.ByteBuffer buffer) {
		return new ByteBuffer(buffer, false);
	}
	
	/**
	 * 封装指定字节数组段
	 * 
	 * @param byteArray
	 * @param offset
	 * @param length
	 * @return
	 */
	public static ByteBuffer wrap(byte[] byteArray, int offset, int length) {
		return new ByteBuffer(org.apache.mina.common.ByteBuffer.wrap(byteArray, offset, length), false);
	}
	
	/**
	 * 分派指定的容量
	 * 
	 * @param capacity
	 * @return
	 */
	public static ByteBuffer allocate(int capacity) {
		return new ByteBuffer(org.apache.mina.common.ByteBuffer.allocate(capacity), true);
	}
	
	/**
	 * 是否用直接缓冲区形式分配
	 * 
	 * @param capacity
	 * @param direct
	 * @return
	 */
	public static ByteBuffer allocate(int capacity, boolean direct) {
		return new ByteBuffer(org.apache.mina.common.ByteBuffer.allocate(capacity, direct), true);
	}
		
	/**
	 * 用指定的MINA缓冲构建
	 * 
	 * @param buffer
	 */
	private ByteBuffer(org.apache.mina.common.ByteBuffer buffer, boolean allocted) {
		this.buffer = buffer;		
		this.allocted = allocted;
	}
	
	/**
	 * 生成MINA缓冲
	 * 
	 * @return
	 */
	public org.apache.mina.common.ByteBuffer toBuffer() {	
		this.allocted = false;
		return buffer;
	}
	
	/**
	 * 缓冲区中是否还有数据
	 * 
	 * @return
	 */
	public boolean hasRemaining() {
		return buffer.hasRemaining();
	}
	
	/**
	 * 用指定的字符编码器保存指定的字符序列
	 * 
	 * @param val
	 * @param encoder
	 * @return
	 * @throws CharacterCodingException
	 */
	public ByteBuffer putString(CharSequence val, CharsetEncoder encoder) throws CharacterCodingException {
		return buffer.putString(val, encoder) == null ? null : this;
	}
	
	/**
	 * 用指定的字符编码器保存指定长度的字符序列
	 * 
	 * @param val
	 * @param fieldSize
	 * @param encoder
	 * @return
	 * @throws CharacterCodingException
	 */
	public ByteBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException {
		return buffer.putString(val, fieldSize, encoder) == null ? null : this;
	}
	
	/**
	 * 保存
	 * 
	 * @param src
	 * @return
	 */
	public ByteBuffer put(byte[] src) {
		return buffer.put(src) == null ? null : this;
	}
	
	/**
	 * 对象，classloader为当前线程的上下文classloader
	 * 
	 * @return
	 * @throws ClassNotFoundException
	 */
	public Object getObject() throws ClassNotFoundException {
        return buffer.getObject();
    }
	
	/**
	 * 设置对象
	 * 
	 * @param o
	 * @return
	 */
	public void putObject(Object o) {
		buffer.putObject(o);
	}
	
	/**
	 * 对象，指定classloader
	 * 
	 * @param classLoader
	 * @return
	 * @throws ClassNotFoundException
	 */
	public Object getObject(final ClassLoader classLoader)
        throws ClassNotFoundException {
		return buffer.getObject(classLoader);
	}
	
	/**
	 * 缓存中的字节数
	 * 
	 * @return
	 */
	public int remaining() {
		return buffer.remaining();
	}

	/**
	 * 获取引用
	 * 
	 */
	public void acquire() {
		buffer.acquire();
	}
	
	/**
	 * 从缓冲中获取字节到指定的字节数组中
	 * 
	 * @param dst
	 * @return
	 */
	public ByteBuffer get(byte[] dst) {
		return buffer.get(dst) == null ? null : this;
	}

	/**
	 * 转换为字节数据
	 * 
	 * @return
	 */
	public byte[] array() {	
		byte[] dst = new byte[limit() - position()];
		buffer.get(dst);
		return dst;
	}
	
	/**
	 * 获取打印数组
	 * 
	 * @return
	 */
	public byte[] getPrintArray() {
		int oldpos = position();
		byte[] buf = array();
		position(oldpos);
		return buf;
	}

	/**
	 * 字节数据偏移量
	 * 
	 * @return
	 */
	public int arrayOffset() {		
		return buffer.arrayOffset();
	}

	/**
	 * 转换为字符缓冲
	 * 
	 * @return
	 */
	public CharBuffer asCharBuffer() {		
		return buffer.asCharBuffer();
	}

	/**
	 * 转换为双精度缓冲
	 * 
	 * @return
	 */
	public DoubleBuffer asDoubleBuffer() {		
		return buffer.asDoubleBuffer();
	}

	/**
	 * 转换为浮点缓冲
	 * 
	 * @return
	 */
	public FloatBuffer asFloatBuffer() {		
		return buffer.asFloatBuffer();
	}

	/**
	 * 转换为整型缓冲
	 * 
	 * @return
	 */
	public IntBuffer asIntBuffer() {		
		return buffer.asIntBuffer();
	}

	/**
	 * 转换为长整型缓冲
	 * 
	 * @return
	 */
	public LongBuffer asLongBuffer() {		
		return buffer.asLongBuffer();
	}

	/**
	 * 转换为只读缓冲
	 * 
	 * @return
	 */
	public ByteBuffer asReadOnlyBuffer() {		
		return buffer.asReadOnlyBuffer() == null ? null : this;
	}

	/**
	 * 转换为短整型缓冲
	 * 
	 * @return
	 */
	public ShortBuffer asShortBuffer() {		
		return buffer.asShortBuffer();
	}

	/**
	 * 转换为JDK的nio缓冲
	 * 
	 * @return
	 */
	public java.nio.ByteBuffer buf() {		
		return buffer.buf();
	}

	/**
	 * 缓冲容量
	 * 
	 * @return
	 */
	public int capacity() {		
		return buffer.capacity();
	}

	/**
	 * 设置缓冲容量
	 * 
	 * @param capacity
	 * @return
	 */
	public ByteBuffer capacity(int capacity) {		
		return buffer.capacity(capacity) == null ? null : this;
	}

	/**
	 * 清楚缓冲中的内容
	 * 
	 * @return
	 */
	public ByteBuffer clear() {		
		return buffer.clear() == null ? null : this;
	}

	/**
	 * 压缩缓冲
	 * 
	 * @return
	 */
	public ByteBuffer compact() {		
		return buffer.compact() == null ? null : this;
	}

	/**
	 * 复制缓冲
	 * 
	 * @return
	 */
	public ByteBuffer duplicate() {		
		return buffer.duplicate() == null ? null : this;
	}

	/**
	 * 扩展缓冲
	 * 
	 * @param pos
	 * @param expectedRemaining
	 * @return
	 */
	public ByteBuffer expand(int pos, int expectedRemaining) {		
		return buffer.expand(pos, expectedRemaining) == null ? null : this;
	}

	/**
	 * 缓冲反转
	 * 
	 * @return
	 */
	public ByteBuffer flip() {		
		return buffer.flip() == null ? null : this;
	}

	/**
	 * 从缓冲中获取字节
	 * 
	 * @return
	 */
	public byte get() {		
		return buffer.get();
	}

	/**
	 * 从缓冲中获取指定位置的字节
	 * 
	 * @param index
	 * @return
	 */
	public byte get(int index) {		
		return buffer.get(index);
	}

	/**
	 * 获取指定位置处的指定长度的字节中指定的目标字节数组中
	 * 
	 * @param dst
	 * @param offset
	 * @param length
	 * @return
	 */
	public ByteBuffer get(byte[] dst, int offset, int length) {		
		return buffer.get(dst, offset, length) == null ? null : this;
	}

	/**
	 * 获取字符
	 * 
	 * @return
	 */
	public char getChar() {		
		return buffer.getChar();
	}

	/**
	 * 获取指定位置处的字符
	 * 
	 * @param index
	 * @return
	 */
	public char getChar(int index) {		
		return buffer.getChar(index);
	}

	/**
	 * 获取double型数据
	 * 
	 * @return
	 */
	public double getDouble() {		
		return buffer.getDouble();
	}

	/**
	 * 获取指定位置处的double型数据
	 * 
	 * @param index
	 * @return
	 */
	public double getDouble(int index) {		
		return buffer.getDouble(index);
	}

	/**
	 * 获取浮点型数据
	 * 
	 * @return
	 */
	public float getFloat() {		
		return buffer.getFloat();
	}

	/**
	 * 获取指定位置的浮点型数据
	 * 
	 * @param index
	 * @return
	 */
	public float getFloat(int index) {		
		return buffer.getFloat(index);
	}

	/**
	 * 获取整型数据
	 * 
	 * @return
	 */
	public int getInt() {		
		return buffer.getInt();
	}

	/**
	 * 获取指定位置的整型数据
	 * 
	 * @param index
	 * @return
	 */
	public int getInt(int index) {		
		return buffer.getInt(index);
	}

	/**
	 * 获取长整型数据
	 * 
	 * @return
	 */
	public long getLong() {		
		return buffer.getLong();
	}

	/**
	 * 获取指定位置处的长整型数据
	 * 
	 * @param index
	 * @return
	 */
	public long getLong(int index) {		
		return buffer.getLong(index);
	}

	/**
	 * 获取短整型数据
	 * 
	 * @return
	 */
	public short getShort() {		
		return buffer.getShort();
	}

	/**
	 * 获取指定位置的短整型数据
	 * 
	 * @param index
	 * @return
	 */
	public short getShort(int index) {		
		return buffer.getShort(index);
	}

	/**
	 * 是否可以自动扩展
	 * 
	 * @return
	 */
	public boolean isAutoExpand() {		
		return buffer.isAutoExpand();
	}

	/**
	 * 是否直接缓冲
	 * 
	 * @return
	 */
	public boolean isDirect() {		
		return buffer.isDirect();
	}

	/**
	 * 是否已经被池化
	 * 
	 * @return
	 */
	public boolean isPooled() {		
		return buffer.isPooled();
	}

	
	/**
	 * 是否只读
	 * 
	 * @return
	 */
	public boolean isReadOnly() {		
		return buffer.isReadOnly();
	}

	/**
	 * 限制
	 * 
	 * @return
	 */
	public int limit() {		
		return buffer.limit();
	}
	
	/**
	 * 设置限制
	 * 
	 * @param limit
	 * @return
	 */
	public ByteBuffer limit(int limit) {		
		return buffer.limit(limit) == null ? null : this;
	}

	/**
	 * 标记
	 * 
	 * @return
	 */
	public ByteBuffer mark() {		
		return buffer.mark() == null ? null : this;
	}

	/**
	 * 标记值
	 * 
	 * @return
	 */
	public int markValue() {		
		return buffer.markValue();
	}

	public ByteOrder order() {		
		return buffer.order();
	}

	/**
	 * 字节序(默认为大端字节序, 即网络字节序)
	 * 
	 * @param order
	 * @return
	 */
	public ByteBuffer order(ByteOrder order) {		
		return buffer.order(order) == null ? null : this;
	}

	/**
	 * 当前位置
	 * 
	 * @return
	 */	
	public int position() {		
		return buffer.position();
	}

	/**
	 * 设置位置
	 * 
	 * @param pos
	 * @return
	 */
	public ByteBuffer position(int pos) {		
		return buffer.position(pos) == null ? null : this;
	}

	/**
	 * 写字节序
	 * 
	 * @param b
	 * @return
	 */
	public ByteBuffer put(byte b) {		
		return buffer.put(b) == null ? null : this;
	}

	/**
	 * 写JDK的nio数据
	 *  
	 * @param nb
	 * @return
	 */
	public ByteBuffer put(java.nio.ByteBuffer nb) {		
		return buffer.put(nb) == null ? null : this;
	}
	
	/**
	 * 写缓存数据
	 * 
	 * @param b
	 * @return
	 */
	public ByteBuffer put(ByteBuffer src) {		
		return buffer.put(src.toBuffer()) == null ? null : this;
	}

	/**
	 * 在指定位置处写
	 * 
	 * @param index
	 * @param b
	 * @return
	 */
	public ByteBuffer put(int index, byte b) {		
		return buffer.put(index, b) == null ? null : this;
	}
    
	/**
	 * 写指定字节数据中的数据
	 * 
	 * @param src
	 * @param offset
	 * @param length
	 * @return
	 */
	public ByteBuffer put(byte[] src, int offset, int length) {		
		return buffer.put(src, offset, length) == null ? null : this;
	}

	/**
	 * 保存字符
	 * 
	 * @param c
	 * @return
	 */
	public ByteBuffer putChar(char c) {		
		return buffer.putChar(c) == null ? null : this;
	}

	/**
	 * 保存字符到指定位置
	 * 
	 * @param index
	 * @param c
	 * @return
	 */
	public ByteBuffer putChar(int index, char c) {		
		return buffer.putChar(index, c) == null ? null : this;
	}

	/**
	 * 保存双精度数据
	 * 
	 * @param d
	 * @return
	 */
	public ByteBuffer putDouble(double d) {		
		return buffer.putDouble(d) == null ? null : this;
	}

	/**
	 * 保存双精度数据到指定位置
	 * 
	 * @param index
	 * @param d
	 * @return
	 */
	public ByteBuffer putDouble(int index, double d) {		
		return buffer.putDouble(index, d) == null ? null : this;
	}

	/**
	 * 保存浮点型数据
	 * 
	 * @param f
	 * @return
	 */
	public ByteBuffer putFloat(float f) {		
		return buffer.putFloat(f) == null ? null : this;
	}

	/**
	 * 保存浮点型数据到指定位置
	 * 
	 * @param index
	 * @param f
	 * @return
	 */
	public ByteBuffer putFloat(int index, float f) {		
		return buffer.putFloat(index, f) == null ? null : this;
	}

	/**
	 * 保存整型数据
	 * 
	 * @param i
	 * @return
	 */
	public ByteBuffer putInt(int i) {		
		return buffer.putInt(i) == null ? null : this;
	}

	/**
	 * 保存整型数据到指定位置
	 * 
	 * @param index
	 * @param i
	 * @return
	 */
	public ByteBuffer putInt(int index, int i) {	
		buffer.putInt(index, i);
		return this;
	}

	/**
	 * 保存长整型数据
	 * 
	 * @param l
	 * @return
	 */
	public ByteBuffer putLong(long l) {	
		return buffer.putLong(l) == null ? null : this;
	}

	/**
	 * 保存长整型数据到指定位置
	 * 
	 * @param index
	 * @param l
	 * @return
	 */
	public ByteBuffer putLong(int index, long l) {			
		return buffer.putLong(index, l) == null ? null : this;
	}

	/**
	 * 保存短整型数据
	 * 
	 * @param s
	 * @return
	 */
	public ByteBuffer putShort(short s) {		
		return buffer.putShort(s) == null ? null : this;
	}

	/**
	 * 保存短整型数据到指定位置
	 * 
	 * @param index
	 * @param s
	 * @return
	 */
	public ByteBuffer putShort(int index, short s) {		
		return buffer.putShort(index, s) == null ? null : this;
	}

	/**
	 * 释放
	 * 
	 */
	public void release() {
		if (released || !allocted) {
			return;
		}
		buffer.release();
		released = true;
	}
	
	@Override
	protected void finalize() throws Throwable {
		try {
		    release();
		} catch (Throwable t) {			
		}
		super.finalize();
	}

	/**
	 * 重置
	 * 
	 * @return
	 */
	public ByteBuffer reset() {		
		return buffer.reset() == null ? null : this;
	}

	/**
	 * 回绕
	 * 
	 * @return
	 */
	public ByteBuffer rewind() {		
		return buffer.rewind() == null ? null : this;
	}

	/**
	 * 设置为自动扩展
	 * 
	 * @param autoExpand
	 * @return
	 */
	public ByteBuffer setAutoExpand(boolean autoExpand) {		
		return buffer.setAutoExpand(autoExpand) == null ? null : this;
	}

	/**
	 * 设置是否池化
	 * 
	 * @param pooled
	 */
	public void setPooled(boolean pooled) {
		buffer.setPooled(pooled);
	}

	/**
	 * 分片
	 * 
	 * @return
	 */
	public ByteBuffer slice() {		
		return buffer.slice() == null ? null : this;
	}

	/**
	 * 关联session
	 * 
	 * @return
	 */
	public IoSession getSession() {
		if (ioSession == null) {
			throw new UIPServiceException("No session for this ByteBuffer");
		}
		return ioSession;
	}

	/**
	 * 设置关联session
	 * 
	 * @param session
	 */
	public void setSession(IoSession session) {
		this.ioSession = session;
	}	
}
